package com.ay.smartpark.sdk.common.base;

import com.ay.smartpark.sdk.common.exception.BaseException;
import com.ay.smartpark.sdk.common.exception.CommonEnum;
import com.ay.smartpark.sdk.common.exception.ResultBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wudi
 */
@Slf4j
@RestControllerAdvice
public class BaseController {

    //定义exceptionHandler解决违背controller层吸收的exception
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Object handlerExcetion(Exception e) {
        if (e instanceof BaseException) {
            BaseException baseException = (BaseException) e;
            return ResultBody.error(baseException.getCode(), baseException.getMessage());
        } else {
            log.error("发生后台错误，原因 {}", e.getMessage());
            return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 处理空指针的异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseBody
    public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){
        log.error("发生空指针异常！原因是: {}",e);
        return ResultBody.error(CommonEnum.INTERNAL_NULLPOINTER_ERROR);
    }


    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Object handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.error("发生后台错误，原因 {}", e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.BAD_REQUEST.value()),e.getMessage());
    }

    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Object handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.error("发生后台错误，原因 {}", e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.BAD_REQUEST.value()),e.getMessage());
    }

    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("参数验证失败 {}", e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.BAD_REQUEST.value()),e.getMessage());
    }

    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BindException.class)
    public Object handleBindException(BindException e) {
        log.error("参数验证失败 {}", e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.BAD_REQUEST.value()),e.getMessage());
    }


    /*    *//**
     * 400 - Bad Request
     *//*
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ConstraintViolationException.class)
    public Object handleServiceException(ConstraintViolationException e) {
        logger.error("参数验证失败", e);
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        ConstraintViolation<?> violation = violations.iterator().next();
        String message = violation.getMessage();
        return "参数验证失败" + message;
    }*/

    /*    *//**
     * 400 - Bad Request
     *//*
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ValidationException.class)
    public Object handleValidationException(ValidationException e) {
        logger.error("参数验证失败", e);
        return "参数验证失败";
    }*/

    /**
     * 404 - Not Found
     */
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public Object noHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) {
        log.error("{} 没有发现该请求 {}", request.getRequestURL(),e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.NOT_FOUND.value()),e.getMessage());
    }


    /**
     * 405 - Method Not Allowed
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Object handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.error(" {}该请求不允许访问,{}", request.getRequestURL(),e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value()),e.getMessage());
    }

    /**
     * 415 - Unsupported Media Type
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Object handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, HttpServletRequest request) {

        log.error("{} 请求错误 {}", request.getRequestURL(),e.getMessage());
        return ResultBody.error(String.valueOf(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value()),e.getMessage());
    }
    /**
     * 业务层需要自己声明异常的情况
     */
/*    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(ServiceException.class)
    public Object handleServiceException(ServiceException e) {
        logger.error("业务逻辑异常", e);
        return "业务逻辑异常：" + e.getMessage();
    }*/
    /**
     * 操作数据或库出现异常
     */
/*    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(DataDoException.class)
    public Object handleException(DataDoException e) {
        logger.error("操作数据库出现异常:", e);
        return "操作数据库出现异常：字段重复、有外键关联等";
    }*/

    /**
     * 500 - Internal Server Error
     */
/*    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
        logger.error("通用异常", e);
        return "500通用异常：" + e.getMessage();
    }*/

    /**
     * 获取其它异常。包括500
     * @param e
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = Exception.class)
    public Object defaultErrorHandler(Exception e){
        log.error("发生后台错误，原因 {}", e.getMessage());
        return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
    }

}
